/*
 *    Copyright (c) 2014 Xiang Xu <xuxiang@mail.bnu.edu.cn>
 *
 *    Permission is hereby granted, free of charge, to any person
 *    obtaining a copy of this software and associated documentation
 *    files (the "Software"), to deal in the Software without
 *    restriction, including without limitation the rights to use,
 *    copy, modify, merge, publish, distribute, sublicense, and/or sell
 *    copies of the Software, and to permit persons to whom the
 *    Software is furnished to do so, subject to the following
 *    conditions:
 *
 *    The above copyright notice and this permission notice shall be
 *    included in all copies or substantial portions of the Software.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 *    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 *    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *    OTHER DEALINGS IN THE SOFTWARE.
 */

#include "shape_symbol.h"
#include "facade_grammar.h"
#include <assert.h>

ShapeSymbol::ShapeSymbol(boost::shared_ptr<FacadeGrammar> facade_grammar)
{
    facade_grammar_ = facade_grammar;
}

ShapeSymbol::ShapeSymbol(int x, int y, int w, int h, std::string name, boost::shared_ptr<FacadeGrammar> facade_grammar)
{
    facade_grammar_ = facade_grammar;

    this->is_terminal_ = false;
    this->is_atom_ = false;
    this->SetScope(x, y, w, h);
    this->set_symbol_name(name);
}

void ShapeSymbol::SetScope(int x, int y, int w, int h)
{
    position_x_ = x;
    position_y_ = y;
    width_ = w;
    height_ = h;
}

void ShapeSymbol::set_symbol_name(std::string value)
{
    symbol_name_ = value;

    this->is_atom_ = false;
    this->is_terminal_ = false;

    if(symbol_name_ == facade_grammar_->get_atom_symbol())
        this->is_atom_ = true;

    for(int i = 0; i < facade_grammar_->get_terminal_symbol_size(); ++i)
    {
        if(symbol_name_ == facade_grammar_->get_terminal_symbol(i))
        {
            this->is_terminal_ = true;
            break;
        }
    }
}


bool ShapeSymbol::DoSplit(ShapeGrammar& shape_grammar, double split_parameter, boost::shared_ptr<ShapeSymbol> right_symbol_1,
                          boost::shared_ptr<ShapeSymbol> right_symbol_2)
{
    // assert that the shape grammar is suitable
    assert(shape_grammar.left_hand_symbol_ == this->symbol_name_);

    if(shape_grammar.apply_direction_ == 0) // vertical action
    {
        if(split_parameter >= height_) // split fail...
        {
            right_symbol_1->SetScope(this->position_x_, this->position_y_, this->width_, this->height_);
            right_symbol_1->set_symbol_name(shape_grammar.exception_symbol_);

            return false;
        }
        else
        {
            right_symbol_1->SetScope(this->position_x_, this->position_y_, this->width_, split_parameter);
            right_symbol_1->set_symbol_name(shape_grammar.right_hand_symbol1_);

            right_symbol_2->SetScope(this->position_x_, this->position_y_ + split_parameter,
                                     this->width_, this->height_ - split_parameter);
            right_symbol_2->set_symbol_name(shape_grammar.right_hand_symbol2_);

            return true;
        }
    }
    else	// horizontal action
    {
        if(split_parameter >= width_)  // split fail ...
        {
            right_symbol_1->SetScope(this->position_x_, this->position_y_, this->width_, this->height_);
            right_symbol_1->set_symbol_name(shape_grammar.exception_symbol_);

            return false;
        }
        else
        {
            right_symbol_1->SetScope(this->position_x_, this->position_y_, split_parameter, this->height_);
            right_symbol_1->set_symbol_name(shape_grammar.right_hand_symbol1_);

            right_symbol_2->SetScope(this->position_x_ + split_parameter, this->position_y_,
                                     this->width_ - split_parameter, this->height_);
            right_symbol_2->set_symbol_name(shape_grammar.right_hand_symbol2_);

            return true;
        }
    }
}
